/**
 * @author hfutrell
 */

 function shaderProgram(stringVertex, stringFragment) {

	if (!stringVertex || !stringFragment) {
		alert("Passed null strings!");
		return null;
	}
	
	this._program = gl.createProgram();
	this.vertexShader = gl.createShader(gl.VERTEX_SHADER);
	this.fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

	var compileShader = function(shader, text) {
		gl.shaderSource(shader, text);
		gl.compileShader(shader);
		return gl.getShaderParameter(shader, gl.COMPILE_STATUS);
	};

	if (compileShader(this.vertexShader, stringVertex) === false) {
		console.error("Vertex Shader failed to compile: " + this.vertexShaderInformationLog() );
		return null;
	}
	if (compileShader(this.fragmentShader, stringFragment) === false) {
		console.error("Fragment Shader failed to compile: " + this.fragmentShaderInformationLog() );
		return null;	
	}

	gl.attachShader(this._program, this.vertexShader);		
	gl.attachShader(this._program, this.fragmentShader);

	if ( this.vertexShader ) {
		gl.deleteShader( this.vertexShader );
	}
	if ( this.fragmentShader ) {
		gl.deleteShader( this.fragmentShader );
	}	
			
 }
 
 /* member variables */
 shaderProgram.prototype._program = null;
 shaderProgram.prototype.vertexShader = null;
 shaderProgram.prototype.fragmentShader = null;
 shaderProgram.prototype._isLinked = false;

// uh oh, this is supposed to be private!
shaderProgram.prototype.informationLogForShader = function(shader) {
	return gl.getShaderInfoLog(shader);
};

shaderProgram.prototype.validateProgram = function() {
	gl.validateProgram(this._program);
	return gl.getProgramParameter(this._program, gl.VALIDATE_STATUS);
};

shaderProgram.prototype.linkProgram = function() {
	gl.linkProgram(this._program);
	if (!gl.getProgramParameter(this._program, gl.LINK_STATUS)) {
		return false;
	}
	else {
		this._isLinked = true;
		return true;
	}
};

shaderProgram.prototype.useProgram = function() {
	gl.useProgram(this._program);
};

shaderProgram.prototype.locationForUniform = function(uniformName) {
	return gl.getUniformLocation(this._program, uniformName);
};
shaderProgram.prototype.bindAttributeToLocation = function(attribute, location) {
	gl.bindAttribLocation(this._program, location, attribute);
};
shaderProgram.prototype.locationForAttribute = function(attributeName) {
	return gl.getAttribLocation(this._program, attributeName);
};

Object.defineProperty(shaderProgram.prototype, "isLinked", {
    get: function(){
        return this._isLinked;
    },
    enumerable: true,
    configurable: true
});

Object.defineProperty(shaderProgram.prototype, "program", {
    get: function(){
        return this._program;
    },
    enumerable: true,
    configurable: true
});

shaderProgram.prototype._programInformationLog = function() {
	return gl.getProgramInfoLog(this._program);
};

shaderProgram.prototype.fragmentShaderInformationLog = function() {
	return this.informationLogForShader(this.fragmentShader);
};

shaderProgram.prototype.vertexShaderInformationLog = function() {
	return this.informationLogForShader(this.vertexShader);
};
